(function ($) {
	$.browserInput = function() {
		return $.browserStorage;
	};
    
	$.fn.browserInput = function (options) {
	    $(this).each(function () {
	        return $.browserInput.impl
	            .init(options)
	            .protect(this);
	    });
	};

	$.browserInput.impl = {
	    
	    init: function(options) {
	        var defaults = {
	            key: '',
	            includes: '*',
	            excludes: '',
	            timeout: 3,
	            reset: false
	        };
	        this.options = $.extend(defaults, options);
	        return this;
	    },

		protect: function(target) {
			if (!$.browserStorage)
			    return false;
			if (target === undefined || !target)
		        return false;
			this.target = target;
			if (this.options.reset)
			    this._reset();
		    else
			    this._restore();
			var self = this;
			setTimeout((function() {
			    function timeout() {
			        self._persist();
			        setTimeout(timeout, self.options.timeout * 1000);
			    }
			    return timeout;
			})(), self.options.timeout * 1000);
		    return true;
		},

		_persist: function () {
		    var targetId = $(this.target).attr('id');
			if (targetId === undefined || !targetId)
			    return;
			var fields = $(this.target)
			    .find(this.options.includes)
		        .not(this.options.excludes);
			var data = this._pack(fields);
			jQuery.browserStorage.setItem(this.options.key, data);
			setTimeout(this._persist, this.options.timeout * 1000);
		},

		_restore: function () {
			var data = jQuery.browserStorage.getItem(this.options.key);
			if (!data)
			    return;
		    var fields = $(this.target)
			    .find(this.options.includes)
		        .not(this.options.excludes);
		    this._unpack(fields, data);
		},

		_reset: function () {
		    jQuery.browserStorage.removeItem(this.options.key);
		},

		_pack: function (items) {
			var data = [];
		    $(items).each(function () {
				var field = $(this);
				var fieldName = field.attr('name');
				if (fieldName === undefined || !fieldName)
				    return true;
				var fieldData = {
				    name: fieldName,
				    data: field.val()
				};
				if (field.is(":checkbox")) {
				    if (fieldName.indexOf('[') !== -1) {
				        fieldData.value = [];
				        $('[name="' + fieldName + '"]:checked').each(function () {
				            fieldData.value.push($(this).val());
				        });
				    } else
				        fieldData.value = field.is(':checked');
				} else if (field.is(':radio')) {
				    if (field.is(':checked'))
				        fieldData.value = field.val();
				}
				data.push(fieldData);
				return true;
			});
		    return data;
		},
				
                
		_unpack: function (items, data) {
		    $(items).each(function () {
				var field = $(this);
				var fieldName = field.attr('name');
				if (fieldName === undefined || !fieldName)
				    return true;
				var fieldData = jQuery.grep(data, function (i) {
				    return i.name == field.attr('name');
				});
				if (fieldData === undefined || !fieldData || fieldData.length == 0)
				    return true;
		        fieldData = fieldData[0].data;
				if (field.is(':checkbox') && fieldData.value !== 'false' && fieldName.indexOf('[') === -1)
				    field.attr('checked', 'checked');
				else if (field.is('checkbox') && fieldData.value === 'false' && fieldName.indexOf("[") === -1)
				    field.removeAttr('checked');
				else if(field.is(':radio')) {
				    if (field.val() === fieldData.value)
				        field.attr('checked', 'checked');
				} else if (fieldName.indexOf('[') === -1)
				    field.val(fieldData);
				else
				    field.val(fieldData.split(','));
				return true;
			});
		}
	};
})(jQuery);
